//
//  UIView+HLEEmptyView.m
//  HLEEmptyView
//
//  Created by hle1 on 2020/9/12.
//

#import "UIView+HLEEmptyView.h"
#import <objc/runtime.h>
#import <Masonry/Masonry.h>
#import <ReactiveObjC/ReactiveObjC.h>
#import <YYCategories/YYCategories.h>


@implementation UIView (HLEEmptyView)

#pragma mark ============ 公开方法 ==============

- (void)hle_showNoInterNetView
{
    [self hle_hide];
    self.noInternetView.hidden = NO;
    [self bringSubviewToFront:self.noInternetView];
}

- (void)hle_hiddenNoInterNetView
{
    self.noInternetView.hidden = YES;
}

- (void)hle_startLoading
{
    self.emptyView.hidden = YES;
}

- (void)hle_endLoading
{
    self.emptyView.hidden = [self hle_totalDataCount];
}

#pragma mark ============ 私有方法 ==============

- (void)hle_getDataAndSet{
    
    if (!self.emptyView && !self.noInternetView) return;

    if (self.networkState) {
        self.emptyView.hidden = YES;
        return;
    }

    if ([self hle_totalDataCount] == 0) {
        [self hle_show];
    }else{
        [self hle_hide];
    }
}

- (void)hle_show{
    if (self.noInternetView && !self.noInternetView.hidden) {
        return;
    }
    [self hle_hiddenNoInterNetView];
    self.emptyView.hidden = NO;
    [self bringSubviewToFront:self.emptyView];
}

- (void)hle_hide{
    self.emptyView.hidden = YES;
    [self hle_hiddenNoInterNetView];
}

- (NSInteger)hle_totalDataCount
{
    NSInteger totalCount = 0;
    if ([self isKindOfClass:[UITableView class]]) {
        UITableView *tableView = (UITableView *)self;
        
        for (NSInteger section = 0; section < tableView.numberOfSections; section++) {
            totalCount += [tableView numberOfRowsInSection:section];
        }
    } else if ([self isKindOfClass:[UICollectionView class]]) {
        UICollectionView *collectionView = (UICollectionView *)self;
        
        for (NSInteger section = 0; section < collectionView.numberOfSections; section++) {
            totalCount += [collectionView numberOfItemsInSection:section];
        }
    }
    return totalCount;
}



#pragma mark ============ setter/getter ==============
- (void)setEmptyView:(HLEEmptyDataView *)emptyView
{
    if (self.emptyView != emptyView) {
        objc_setAssociatedObject(self, @selector(setEmptyView:), emptyView, OBJC_ASSOCIATION_RETAIN);
        [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isMemberOfClass:NSClassFromString(@"HLEEmptyDataView")]) {
                [obj removeFromSuperview];
            }
        }];
        [self addSubview:emptyView];
        
        [emptyView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.mas_equalTo(0);
            make.left.mas_greaterThanOrEqualTo(20);
            make.right.mas_lessThanOrEqualTo(-20);
        }];
        if ([self isKindOfClass:[UITableView class]] || [self isKindOfClass:[UICollectionView class]]) {
            [self hle_getDataAndSet];
        } else {
            self.emptyView.hidden = YES;
        }
    }
}

- (HLEEmptyDataView *)emptyView
{
    return objc_getAssociatedObject(self, @selector(setEmptyView:));
}


- (void)setNoInternetView:(HLENoInternetView *)noInternetView
{
    if (self.noInternetView != noInternetView) {
        objc_setAssociatedObject(self, @selector(setNoInternetView:), noInternetView, OBJC_ASSOCIATION_RETAIN);
        [self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isMemberOfClass:NSClassFromString(@"HLENoInternetView")]) {
                [obj removeFromSuperview];
            }
        }];
        [self addSubview:noInternetView];
        [self hle_hiddenNoInterNetView];
        [noInternetView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.mas_equalTo(0);
            make.left.mas_greaterThanOrEqualTo(20);
            make.right.mas_lessThanOrEqualTo(-20);
        }];
    }
}

- (HLENoInternetView *)noInternetView
{
    return objc_getAssociatedObject(self, @selector(setNoInternetView:));
}

- (void)setNetworkState:(BOOL)networkState
{
    objc_setAssociatedObject(self, @selector(setNetworkState:), @(networkState), OBJC_ASSOCIATION_ASSIGN);
}

- (BOOL)networkState
{
    return [objc_getAssociatedObject(self, @selector(setNetworkState:)) boolValue];
}
@end

#pragma mark ============ UITableView ==============

@implementation UITableView (Empty)

+ (void)load{
    
    [self swizzleInstanceMethod:@selector(reloadData) with:@selector(hlereloadData)];
        
    ///section
    [self swizzleInstanceMethod:@selector(insertSections:withRowAnimation:) with:@selector(hleinsertSections:withRowAnimation:)];
    
    [self swizzleInstanceMethod:@selector(deleteSections:withRowAnimation:) with:@selector(hledeleteSections:withRowAnimation:)];
    [self swizzleInstanceMethod:@selector(reloadSections:withRowAnimation:) with:@selector(hlereloadSections:withRowAnimation:)];
    
    ///row
    [self swizzleInstanceMethod:@selector(insertRowsAtIndexPaths:withRowAnimation:) with:@selector(hleinsertRowsAtIndexPaths:withRowAnimation:)];
    [self swizzleInstanceMethod:@selector(deleteRowsAtIndexPaths:withRowAnimation:) with:@selector(hledeleteRowsAtIndexPaths:withRowAnimation:)];
    [self swizzleInstanceMethod:@selector(reloadRowsAtIndexPaths:withRowAnimation:) with:@selector(hlereloadRowsAtIndexPaths:withRowAnimation:)];
}
- (void)hlereloadData{
    [self hlereloadData];
    [self hle_getDataAndSet];
}
///section
- (void)hleinsertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{
    [self hleinsertSections:sections withRowAnimation:animation];
    [self hle_getDataAndSet];
}
- (void)hledeleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{
    [self hledeleteSections:sections withRowAnimation:animation];
    [self hle_getDataAndSet];
}
- (void)hlereloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{
    [self hlereloadSections:sections withRowAnimation:animation];
    [self hle_getDataAndSet];
}

///row
- (void)hleinsertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{
    [self hleinsertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
    [self hle_getDataAndSet];
}
- (void)hledeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{
    [self hledeleteRowsAtIndexPaths:indexPaths withRowAnimation:animation];
    [self hle_getDataAndSet];
}
- (void)hlereloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation{
    [self hlereloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
    [self hle_getDataAndSet];
}


@end

#pragma mark ============ UICollectionView ==============

@implementation UICollectionView (Empty)

+ (void)load{
    
    [self swizzleInstanceMethod:@selector(reloadData) with:@selector(hlereloadData)];
    
    ///section
    [self swizzleInstanceMethod:@selector(insertSections:) with:@selector(hleinsertSections:)];
    [self swizzleInstanceMethod:@selector(deleteSections:) with:@selector(hledeleteSections:)];
    [self swizzleInstanceMethod:@selector(reloadSections:) with:@selector(hlereloadSections:)];
    
    ///item
    [self swizzleInstanceMethod:@selector(insertItemsAtIndexPaths:) with:@selector(hleinsertItemsAtIndexPaths:)];
    [self swizzleInstanceMethod:@selector(deleteItemsAtIndexPaths:) with:@selector(hledeleteItemsAtIndexPaths:)];
    [self swizzleInstanceMethod:@selector(reloadItemsAtIndexPaths:) with:@selector(hlereloadItemsAtIndexPaths:)];
    
}
- (void)hlereloadData{
    [self hlereloadData];
    [self hle_getDataAndSet];
}
///section
- (void)hleinsertSections:(NSIndexSet *)sections{
    [self hleinsertSections:sections];
    [self hle_getDataAndSet];
}
- (void)hledeleteSections:(NSIndexSet *)sections{
    [self hledeleteSections:sections];
    [self hle_getDataAndSet];
}
- (void)hlereloadSections:(NSIndexSet *)sections{
    [self hlereloadSections:sections];
    [self hle_getDataAndSet];
}

///item
- (void)hleinsertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
    [self hleinsertItemsAtIndexPaths:indexPaths];
    [self hle_getDataAndSet];
}
- (void)hledeleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
    [self hledeleteItemsAtIndexPaths:indexPaths];
    [self hle_getDataAndSet];
}
- (void)hlereloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
    [self hlereloadItemsAtIndexPaths:indexPaths];
    [self hle_getDataAndSet];
}


@end

#pragma mark ============ HLEEmptyViewnNetObject ==============

@implementation HLEEmptyViewnNetObject

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static HLEEmptyViewnNetObject *instance = nil;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    return [self sharedInstance];
}

@end

